﻿using STimer;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
// gameObject 扩展

public static class UnityEngineExtensions
{
    public static Transform GetOrAddNode(this GameObject gb, string strNode)
    {
        var obj = gb.FindDeepChildByName(strNode);
        if (obj != null)
            return obj.transform;
        obj = new GameObject(strNode);
        obj.transform.parent = gb.transform;
        obj.transform.localPosition = Vector3.zero;
        return obj.transform;
    }
    public static void ShowChildActive(this GameObject gb)
    {
        string str = "";
        var nodes = gb.transform.GetComponentsInChildren<Transform>(true);
        foreach (var node in nodes)
        {
            str += node.name + "   =" + node.gameObject.activeInHierarchy.ToString() + "\n";
        }
        SG.LogMgr.Instance().LogError(str);
    }
    public static T GetOrAddComponent<T>(this GameObject gb) where T : UnityEngine.Component
    {

        if (gb == null)
        {
            return null;
        }
        var com = gb.GetComponent<T>();
        if (com == null)
            com = gb.AddComponent<T>();
        return com;
    }
    public static string GetFullName(this GameObject obj)
    {
        string str = obj.name;
        Transform parent = obj.transform.parent;
        while (parent != null)
        {
            str = parent.name + "->" + str;
            parent = parent.parent;
        }
        return str;
    }
    public static List<string> GetDescriptions(this Enum val)
    {
        var strList = new List<string>();
        var type = val.GetType();
        var memberInfo = type.GetFields();
        foreach (var m in memberInfo)
        {
            if (m.FieldType.Name == type.Name)
            {
                var hds = m.GetCustomAttributes(typeof(DescriptionAttribute), false);
                if (hds == null || hds.Length != 1)
                    strList.Add(m.Name);
                else
                    strList.Add((hds[0] as DescriptionAttribute).Description);
            }
        }
        return strList;
    }
    public static void SetPositionFromUINode(this GameObject gb, Vector3 pos)
    {
        Vector3 worldPos = RectTransformUtility.WorldToScreenPoint(Camera.main, pos);
        worldPos.z = 100;
        gb.transform.position = worldPos;
        worldPos = gb.transform.localPosition;
        worldPos.z = 100;
        gb.transform.localPosition = worldPos;
        gb.transform.localScale = Vector3.one;
    }

    public static void SetObjectZeroParent(this GameObject gb, Transform parent)
    {
        gb.transform.parent = parent;
        gb.transform.localPosition = Vector3.zero;
        gb.transform.localEulerAngles = Vector3.zero;
        gb.transform.localRotation = Quaternion.identity;
        gb.transform.localScale = Vector3.one;
    }
    public static void MakeColor(this GameObject gb, Color color)
    {
        var images = gb.GetComponentsInChildren<Image>();
        foreach (var image in images)
        {
            image.color = color;
        }
        var texts = gb.GetComponentsInChildren<Text>();
        foreach (var text in texts)
        {
            text.color = color;
        }
    }
    // 设置所有节点到新的层

    public static void ChangeLayer(this GameObject gb, string targetLayer)
    {
        if (LayerMask.NameToLayer(targetLayer) == -1)
        {
            XKLog.Log("Layer中不存在,请手动添加LayerName");

            return;
        }
        //遍历更改所有子物体layer
        gb.layer = LayerMask.NameToLayer(targetLayer);
        foreach (Transform child in gb.transform)
        {
            child.gameObject.ChangeLayer(targetLayer);
        }
    }
    // 设置所有节点到新的layer层,如果 strCustomLayer 有值，就是只替换 strCustomLayer 层的节点
    public static bool SetAllChildLayer(this GameObject gb, int layer, string strCustomLayer = "")
    {
        bool modify = false;
        if (gb == null)
            return modify;
        // 如果指定层名字不为空，就设定这个名字的节点
        if (!string.IsNullOrEmpty(strCustomLayer))
        {
            if (gb.layer == LayerMask.NameToLayer(strCustomLayer))
            {
                gb.layer = layer;
                modify = true;
            }
        }
        else
        {
            gb.layer = layer;
            modify = true;
        }
        foreach (Transform child in gb.transform)
            if (child.gameObject.SetAllChildLayer(layer, strCustomLayer))
                modify = true;
        return modify;
    }

    // 设置所有节点到新的layer层,如果 strCustomLayer 有值，就是替换 除了 strCustomLayer 层以外的节点
    public static bool SetAllChildLayerExclude(this GameObject gb, int layer, string strCustomLayer = "")
    {
        bool modify = false;
        if (gb == null)
            return modify;
        if (string.IsNullOrEmpty(strCustomLayer))
        {
            if (gb.layer != LayerMask.NameToLayer(strCustomLayer))
            {
                gb.layer = layer;
                modify = true;
            }
        }
        else
        {
            gb.layer = layer;
            modify = true;
        }
        foreach (Transform child in gb.transform)
            if (child.gameObject.SetAllChildLayerExclude(layer, strCustomLayer))
                modify = true;
        return modify;
    }

    public static bool SetAllChildLayer(this GameObject gb, string strName, string strCustomLayer = "")
    {
        int layer = LayerMask.NameToLayer(strName);
        return SetAllChildLayer(gb, layer, strCustomLayer);
    }
    public static bool SetAllChildLayerExclude(this GameObject gb, string strName, string strCustomLayer = "")
    {
        int layer = LayerMask.NameToLayer(strName);
        return SetAllChildLayerExclude(gb, layer, strCustomLayer);
    }
    public static void SetSpeed(this GameObject gb, float fSpeed)
    {
        var anims = gb.GetComponentsInChildren<Animator>();
        foreach (var anim in anims)
        {
            anim.speed = fSpeed;
        }
        var objs = gb.GetComponentsInChildren<ParticleSystem>();
        foreach (var obj in objs)
        {
            var main = obj.main;
            main.simulationSpeed = fSpeed;
        }

    }
    public static void SetParticleSystemOrder(this GameObject gb, int order)
    {
        var objs = gb.GetComponentsInChildren<ParticleSystem>();
        foreach (var obj in objs)
        {
            var main = obj.GetComponent<ParticleSystemRenderer>();
            main.sortingOrder = order;
        }
    }
    public static void SetAllChildTag(this GameObject gb, string strName)
    {
        if (gb != null)
        {
            gb.tag = strName;
        }
        int count = gb.transform.childCount;
        for (int i = 0; i < count; i++)
        {
            Transform trans = gb.transform.GetChild(i);

            if (trans.childCount > 0)
            {
                trans.gameObject.SetAllChildTag(strName);
            }
            else
            {
                trans.gameObject.tag = strName;
            }
        }
    }



    public static void StopOrDestroy(this GameObject gb)
    {
#if UNITY_EDITOR
        GameObject.Destroy(gb);
#else
                    GameObject.Destroy(gb);
#endif
    }


    public static void ClearChild(this GameObject gb)
    {
        //for (int i = 0; i < gb.transform.childCount; ++i)
        //{
        //    gb.transform.GetChild(i).gameObject.StopOrDestroy();
        //}

        int childcount = gb.transform.childCount;
        for (int i = 0; i < childcount; i++)
        {
            GameObject.DestroyImmediate(gb.transform.GetChild(0).gameObject);
        }
    }
    public static GameObject FindDeepChildByName(this GameObject gb, string strName)
    {
        ++SG.GameLoop.m_nNumber;
        if (gb == null)
        {
            XKLog.LogError("查找节点[{0}]失败", strName);
        }
        if (strName == null)
            return null;
        if (strName == "")
            return null;
        var trans = gb.transform.Find(strName);
        if (trans)
            return trans.gameObject;
        GameObject resultObject = null;
        for (int i = 0; i < gb.transform.childCount; ++i)
        {
            GameObject subObject = gb.transform.GetChild(i).gameObject;
            resultObject = subObject.FindDeepChildByName(strName);
            if (resultObject)
                return resultObject;
        }
        return null;
        //GameObject resultChild = null;
        //if (gb != null && gb.transform.childCount > 0)
        //{
        //    for (int i = 0; i < gb.transform.childCount; ++i)
        //    {
        //        if (gb.transform.GetChild(i).gameObject.name == strName)
        //        {
        //            resultChild = gb.transform.GetChild(i).gameObject;
        //        }
        //    }

        //    if (resultChild == null)
        //    {
        //        for (int i = 0; i < gb.transform.childCount; ++i)
        //        {
        //            resultChild = gb.transform.GetChild(i).gameObject.FindDeepChildByName(strName);
        //            if (resultChild != null)
        //            {
        //                break;
        //            }
        //        }
        //    }
        //}
        //return resultChild;

    } 
    public static Vector2 GetScreenPosition(this GameObject obj, Camera uiCamera)
    {
        var rc = obj.GetComponent<RectTransform>();
        if (rc != null)
        {
            Vector3 worldPos = rc.position;
            Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(uiCamera, worldPos);
            return screenPos;
        }
        return Vector2.zero;
    }
    public static Vector2 SetScreenPosition(this GameObject obj, Vector2 pos, Camera uiCamera)
    {
        var rc = obj.GetComponent<RectTransform>();
        if (rc != null)
        {
            Vector3 worldPos = rc.position;
            Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(uiCamera, worldPos);
            return screenPos;
        }
        return Vector2.zero;
    }

    public static void FaceVector2( this GameObject obj, Vector2 target )
    {
        Vector3 direction = (target - (Vector2)obj.transform.position).normalized;

        // 创建一个围绕Y轴（在2D中，这通常是上下方向）的旋转，使Z轴（面向相机的方向）指向目标  
        // 注意：在2D中，我们通常假设相机是沿Z轴负方向看的，所以我们需要翻转Y和Z来得到正确的2D效果  
        // 但因为SpriteRenderer实际上是在3D空间中，所以我们仍然使用Z轴作为面向方向  
        float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        Quaternion rotation = Quaternion.Euler(0f, 0f, angle);

        // 应用旋转  
        obj.transform.rotation = rotation;
    }
}